%     FASTENER DOCTOR - программа для лечения и конвертации крепежа
%     Copyright (C) 2018  Михаил Козлов
%     Сайт проекта: <http://www.fastenerdoctor.ru/>
%     Адрес электронной почты для связи с разработчиком:
%     <doctor.fastener@gmail.com>
% 
%     Эта программа является свободным программным обеспечением: Вы можете
%     распространять ее и/или изменять, соблюдая условия Универсальной общественной
%     лицензии GNU, опубликованной Фондом свободного программного обеспечения,
%     либо редакции 3, либо (на Ваше усмотрение) любой редакции, выпущенной позже.
% 
%     Эта программа распространяется в надежде на то, что она окажется полезной,
%     но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, включая даже подразумеваемую гарантию ТОВАРНОЙ ПРИГОДНОСТИ,
%     либо ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Ознакомьтесь с Универсальной общественной
%     лицензией GNU для получения более подробной информации.
% 
%     Вы должны были получить копию Универсальной общественной лицензии GNU
%     вместе с этой программой. Если Вы ее не получили, то перейдите по адресу:
%     <http://www.gnu.org/licenses/>.
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <https://www.gnu.org/licenses/>.

function [AST_NODES, AST_COORD, AST_PSETS, AST_MATERIALS] = Create_Associativity_Tables()

% AST_NODES{:,1}
%             ->.Elm_list(:,1)
%             ->.MPC_list(:,1)
%
% AST_COORD{:,1}
%             ->.Node_list(:,1)
%             ->.PSet_list(:,1)
%
% AST_PSETS{:,1}
%             ->.Elm_list(:,1)
%
% AST_MATERIALS{:,1}
%             ->.PSet_list(:,1)

global ErrCode;

global DB_NODES;
global DB_ELEMENTS;
global DB_MPC;
global DB_COORD;
global DB_PSETS;
global DB_MATERIALS;
global DB_FIELDS;

global AT_NODES;
global AT_COORD;
global AT_PSETS;
global AT_MATERIALS;
global AT_FIELDS;

global Progress_Bar_Segments;
global Progress_Bar_Delay;

fprintf (1, 'Создание таблиц ассоциативности...      ');

% Для вывода прогресса
PB_sign = '#';
PB_segments = Progress_Bar_Segments;
PB_N_items_total = 0;

if (~isempty(DB_NODES))
    PB_N_items_total = PB_N_items_total + 3*size(DB_NODES,1);
end

if (~isempty(DB_COORD))
    PB_N_items_total = PB_N_items_total + size(DB_COORD,1);
end

if (~isempty(DB_PSETS))
    PB_N_items_total = PB_N_items_total + 3*size(DB_PSETS,1);
end

if (~isempty(DB_MATERIALS))
    PB_N_items_total = PB_N_items_total + size(DB_MATERIALS,1);
end

if (~isempty(DB_ELEMENTS))
    PB_N_items_total = PB_N_items_total + 2*size(DB_ELEMENTS,1);
end

if (~isempty(DB_MPC))
    PB_N_items_total = PB_N_items_total + 2*size(DB_MPC,1);
end

PB_progress_per_segment = 1/PB_segments;
PB_items_counter = 0;
PB_last_progress = 0;
PB_current_progress = 0; %#ok<NASGU>
PB_N_bars_written = 0;

% --- Выделение памяти ---

if (~isempty(DB_NODES))
    AST_NODES = cell(size(DB_NODES,1),1);
    AST_Nodes_Elm_counter = zeros(size(DB_NODES,1),1);
    AST_Nodes_MPC_counter = zeros(size(DB_NODES,1),1);
else
    AST_NODES = [];
end

if (~isempty(DB_COORD))
    AST_COORD = cell(size(DB_COORD,1),1);
    AST_Coord_Nodes_counter = zeros(size(DB_COORD,1),1);
    AST_Coord_PSets_counter = zeros(size(DB_COORD,1),1);
else
    AST_COORD = [];
end

if (~isempty(DB_PSETS))
    AST_PSETS = cell(size(DB_PSETS,1),1);
    AST_PSets_Elm_counter = zeros(size(DB_PSETS,1),1);
else
    AST_PSETS = [];
end

if (~isempty(DB_MATERIALS))
    AST_MATERIALS = cell(size(DB_MATERIALS,1),1);
    AST_Mat_PSets_counter = zeros(size(DB_MATERIALS,1),1);
else
    AST_MATERIALS = [];
end

% --- Подсчет размеров массивов ---

if (~isempty(DB_ELEMENTS))
    
    for i=1:size(DB_ELEMENTS,1)
        
        if (DB_ELEMENTS{i}.ID ~= -1)
            
            if (~isempty(AST_NODES))
                for j=1:DB_ELEMENTS{i}.N_nodes
                    AST_Nodes_Elm_counter(AT_NODES(DB_ELEMENTS{i}.Nodes(j))) = AST_Nodes_Elm_counter(AT_NODES(DB_ELEMENTS{i}.Nodes(j))) + 1;
                end
            end
            
            if (~isempty(AST_PSETS))
                if (~isempty(DB_ELEMENTS{i}.Prop_ID))
                    AST_PSets_Elm_counter(AT_PSETS(DB_ELEMENTS{i}.Prop_ID)) = AST_PSets_Elm_counter(AT_PSETS(DB_ELEMENTS{i}.Prop_ID)) + 1;
                end
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end
    
end

if (~isempty(DB_MPC))
    
    for i=1:size(DB_MPC,1)
        
        if (DB_MPC{i}.ID ~= -1)
            
            if (~isempty(AST_NODES))
        
                switch DB_MPC{i}.type

                    case 'RBAR'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) + 1;
                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) + 1;

                    case 'RBE2'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) + 1;
                        for j=1:size(DB_MPC{i}.dep_grid,1)
                            AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid(j))) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid(j))) + 1;
                        end

                    case 'RBE3'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) + 1;
                        for j=1:size(DB_MPC{i}.ind_data,1)
                            AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_data(j,2))) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_data(j,2))) + 1;
                        end

                    otherwise

                        fprintf (1, '\nОбнаружен неизвестный тип MPC с номером %i [%s] !\n', DB_MPC{i}.ID, DB_MPC{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;

                end
            
            end
        
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end 
        
    end
    
end

if (~isempty(DB_NODES))
    
    for i=1:size(DB_NODES,1)
        
        if (DB_NODES{i}.ID ~= -1)
            
            if (~isempty(AST_COORD))
            
                if (DB_NODES{i}.Reference_CID ~= 0)
                    AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Reference_CID)) = AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Reference_CID)) + 1;
                end

                if ((DB_NODES{i}.Analysis_CID ~= 0) && (DB_NODES{i}.Analysis_CID ~= DB_NODES{i}.Reference_CID))
                    AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Analysis_CID)) = AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Analysis_CID)) + 1;
                end
            
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end
        
    end
    
end

if (~isempty(DB_PSETS))
    
    for i=1:size(DB_PSETS,1)
        
        if (DB_PSETS{i}.ID ~= -1)
            
            if (~isempty(AST_COORD))
                switch DB_PSETS{i}.type
                    case 'PSOLID'
                        if (DB_PSETS{i}.Ori_CID > 0)
                            AST_Coord_PSets_counter(AT_COORD(DB_PSETS{i}.Ori_CID)) = AST_Coord_PSets_counter(AT_COORD(DB_PSETS{i}.Ori_CID)) + 1;
                        end
                    case {'PCOMP', 'PCOMPG', 'PSHELL'}
                        if (~DB_Field_Isempty(DB_PSETS{i}.Ori_Field_ID))
                            SHELL_CID_counter = 0;
                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(1) == 0)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2) > 0)
                                    SHELL_CID_counter = SHELL_CID_counter + 1;
                                end
                            end
                            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data, 1)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data{j} ~= -1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                                            SHELL_CID_counter = SHELL_CID_counter + 1;
                                        end
                                    end
                                end
                            end
                            if (SHELL_CID_counter > 0)
                                SHELL_CID_Array = zeros(SHELL_CID_counter,1);
                                SHELL_CID_counter = 0;
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(1) == 0)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2) > 0)
                                        SHELL_CID_counter = SHELL_CID_counter + 1;
                                        SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2);
                                    end
                                end
                                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data, 1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data{j} ~= -1)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                                                SHELL_CID_counter = SHELL_CID_counter + 1;
                                                SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2);
                                            end
                                        end
                                    end
                                end
                                SHELL_CID_Array = unique(SHELL_CID_Array);
                                for j=1:size(SHELL_CID_Array,1)
                                    AST_Coord_PSets_counter(AT_COORD(SHELL_CID_Array(j))) = AST_Coord_PSets_counter(AT_COORD(SHELL_CID_Array(j))) + 1;
                                end
                            end
                        end
                    case 'PBUSH'
                        if (~DB_Field_Isempty(DB_PSETS{i}.Ori_CID_Field_ID))
                            PBUSH_CID_counter = 0;
                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default > 0)
                                PBUSH_CID_counter = PBUSH_CID_counter + 1;
                            end
                            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data, 1)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                                        PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                    end
                                end
                            end
                            if (PBUSH_CID_counter > 0)
                                PBUSH_CID_Array = zeros(PBUSH_CID_counter,1);
                                PBUSH_CID_counter = 0;
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default > 0)
                                    PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                    PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default;
                                end
                                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data, 1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                                            PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                            PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j};
                                        end
                                    end
                                end
                                PBUSH_CID_Array = unique(PBUSH_CID_Array);
                                for j=1:size(PBUSH_CID_Array,1)
                                    AST_Coord_PSets_counter(AT_COORD(PBUSH_CID_Array(j))) = AST_Coord_PSets_counter(AT_COORD(PBUSH_CID_Array(j))) + 1;
                                end
                            end
                        end
                    case {'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
                        % Ничего не делаем
                    otherwise
                        fprintf (1, '\nОбнаружен неизвестный тип property set с номером %i [%s] !\n', DB_PSETS{i}.ID, DB_PSETS{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;
                end
            end
            
            if (~isempty(AST_MATERIALS))
                switch DB_PSETS{i}.type
                    case {'PCOMP', 'PCOMPG'}
                        Mat_array = unique(DB_PSETS{i}.Laminate(:,1));
                        for j=1:size(Mat_array,1)
                            AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) = AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) + 1;
                        end
                    case 'PSHELL'
                        Mat_array = zeros(3,1);
                        Mat_array(1) = DB_PSETS{i}.Mat_ID_membrane;
                        Mat_array(2) = DB_PSETS{i}.Mat_ID_bending;
                        Mat_array(3) = DB_PSETS{i}.Mat_ID_transverse_shear;
                        Mat_array = unique(Mat_array);
                        for j=1:size(Mat_array,1)
                            AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) = AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) + 1;
                        end
                    case 'PBUSH'
                        % Ничего не делаем
                    case {'PSOLID', 'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
                        AST_Mat_PSets_counter(AT_MATERIALS(DB_PSETS{i}.Mat_ID)) = AST_Mat_PSets_counter(AT_MATERIALS(DB_PSETS{i}.Mat_ID)) + 1;
                    otherwise
                        fprintf (1, '\nОбнаружен неизвестный тип property set с номером %i [%s] !\n', DB_PSETS{i}.ID, DB_PSETS{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;
                end
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end
        
    end
    
end

% --- Выделение памяти для списков ---

if (~isempty(AST_NODES))
    
    for i=1:size(AST_NODES,1)

        if (DB_NODES{i}.ID ~= -1)
            
            if (AST_Nodes_Elm_counter(i) ~= 0)
                AST_NODES{i}.Elm_list = zeros(AST_Nodes_Elm_counter(i),1);
            else
                AST_NODES{i}.Elm_list = [];
            end
            
            if (AST_Nodes_MPC_counter(i) ~= 0)
                AST_NODES{i}.MPC_list = zeros(AST_Nodes_MPC_counter(i),1);
            else
                AST_NODES{i}.MPC_list = [];
            end
            
        else
            AST_NODES{i}.Elm_list = [];
            AST_NODES{i}.MPC_list = [];
        end

        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end
    
end

if (~isempty(AST_COORD))
    
    for i=1:size(AST_COORD,1)

        if (DB_COORD{i}.ID ~= -1)
            
            if (AST_Coord_Nodes_counter(i) ~= 0)
                AST_COORD{i}.Node_list = zeros(AST_Coord_Nodes_counter(i),1);
            else
                AST_COORD{i}.Node_list = [];
            end
            
            if (AST_Coord_PSets_counter(i) ~= 0)
                AST_COORD{i}.PSet_list = zeros(AST_Coord_PSets_counter(i),1);
            else
                AST_COORD{i}.PSet_list = [];
            end

        else
            AST_COORD{i}.Node_list = [];
            AST_COORD{i}.PSet_list = [];
        end

        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end
    
end

if (~isempty(AST_PSETS))
    
    for i=1:size(AST_PSETS,1)

        if (DB_PSETS{i}.ID ~= -1)
            
            if (AST_PSets_Elm_counter(i) ~= 0)
                AST_PSETS{i}.Elm_list = zeros(AST_PSets_Elm_counter(i),1);
            else
                AST_PSETS{i}.Elm_list = [];
            end
            
        else
            AST_PSETS{i}.Elm_list = [];
        end

        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end

end

if (~isempty(AST_MATERIALS))
    
    for i=1:size(AST_MATERIALS,1)

        if (DB_MATERIALS{i}.ID ~= -1)
            
            if (AST_Mat_PSets_counter(i) ~= 0)
                AST_MATERIALS{i}.PSet_list = zeros(AST_Mat_PSets_counter(i),1);
            else
                AST_MATERIALS{i}.PSet_list = [];
            end
            
        else
            AST_MATERIALS{i}.PSet_list = [];
        end

        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end

end

% --- Обнуление счетчиков ---

if (~isempty(DB_NODES))
    AST_Nodes_Elm_counter = zeros(size(DB_NODES,1),1);
    AST_Nodes_MPC_counter = zeros(size(DB_NODES,1),1);
end

if (~isempty(DB_COORD))
    AST_Coord_Nodes_counter = zeros(size(DB_COORD,1),1);
    AST_Coord_PSets_counter = zeros(size(DB_COORD,1),1);
end

if (~isempty(DB_PSETS))
    AST_PSets_Elm_counter = zeros(size(DB_PSETS,1),1);
end

if (~isempty(DB_MATERIALS))
    AST_Mat_PSets_counter = zeros(size(DB_MATERIALS,1),1);
end

% --- Работа с базой элементов ---

if (~isempty(DB_ELEMENTS))
    
    % Заполнение списков элементов
    for i=1:size(DB_ELEMENTS,1)
        
        if (DB_ELEMENTS{i}.ID ~= -1)
            
            if (~isempty(AST_NODES))
                for j=1:DB_ELEMENTS{i}.N_nodes
                    AST_Nodes_Elm_counter(AT_NODES(DB_ELEMENTS{i}.Nodes(j))) = AST_Nodes_Elm_counter(AT_NODES(DB_ELEMENTS{i}.Nodes(j))) + 1;
                    AST_NODES{AT_NODES(DB_ELEMENTS{i}.Nodes(j))}.Elm_list(AST_Nodes_Elm_counter(AT_NODES(DB_ELEMENTS{i}.Nodes(j)))) = DB_ELEMENTS{i}.ID;
                end
            end
            
            if (~isempty(AST_PSETS))
                if (~isempty(DB_ELEMENTS{i}.Prop_ID))
                    AST_PSets_Elm_counter(AT_PSETS(DB_ELEMENTS{i}.Prop_ID)) = AST_PSets_Elm_counter(AT_PSETS(DB_ELEMENTS{i}.Prop_ID)) + 1;
                    AST_PSETS{AT_PSETS(DB_ELEMENTS{i}.Prop_ID)}.Elm_list(AST_PSets_Elm_counter(AT_PSETS(DB_ELEMENTS{i}.Prop_ID))) = DB_ELEMENTS{i}.ID;
                end
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end

    end
    
end

% --- Работа с базой MPC ---

if (~isempty(DB_MPC))
    
    % Заполнение списков MPC
    for i=1:size(DB_MPC,1)
        
        if (DB_MPC{i}.ID ~= -1)
            
            if (~isempty(AST_NODES))
        
                switch DB_MPC{i}.type

                    case 'RBAR'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) + 1;
                        AST_NODES{AT_NODES(DB_MPC{i}.ind_grid)}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid))) = DB_MPC{i}.ID;

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) + 1;
                        AST_NODES{AT_NODES(DB_MPC{i}.dep_grid)}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid))) = DB_MPC{i}.ID;

                    case 'RBE2'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid)) + 1;
                        AST_NODES{AT_NODES(DB_MPC{i}.ind_grid)}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_grid))) = DB_MPC{i}.ID;

                        for j=1:size(DB_MPC{i}.dep_grid,1)
                            AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid(j))) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid(j))) + 1;
                            AST_NODES{AT_NODES(DB_MPC{i}.dep_grid(j))}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid(j)))) = DB_MPC{i}.ID;
                        end

                    case 'RBE3'

                        AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid)) + 1;
                        AST_NODES{AT_NODES(DB_MPC{i}.dep_grid)}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.dep_grid))) = DB_MPC{i}.ID;

                        for j=1:size(DB_MPC{i}.ind_data,1)
                            AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_data(j,2))) = AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_data(j,2))) + 1;
                            AST_NODES{AT_NODES(DB_MPC{i}.ind_data(j,2))}.MPC_list(AST_Nodes_MPC_counter(AT_NODES(DB_MPC{i}.ind_data(j,2)))) = DB_MPC{i}.ID;
                        end

                    otherwise

                        fprintf (1, '\nОбнаружен неизвестный тип MPC с номером %i [%s] !\n', DB_MPC{i}.ID, DB_MPC{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;

                end
            
            end
        
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end
            
    end
    
end

% --- Работа с базой узлов ---

if (~isempty(DB_NODES))
    
    % Заполнение списков узлов
    
    for i=1:size(DB_NODES,1)
        
        if (DB_NODES{i}.ID ~= -1)
            
            if (~isempty(AST_COORD))
            
                if (DB_NODES{i}.Reference_CID ~= 0)
                    AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Reference_CID)) = AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Reference_CID)) + 1;
                    AST_COORD{AT_COORD(DB_NODES{i}.Reference_CID)}.Node_list(AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Reference_CID))) = DB_NODES{i}.ID;
                end

                if ((DB_NODES{i}.Analysis_CID ~= 0) && (DB_NODES{i}.Analysis_CID ~= DB_NODES{i}.Reference_CID))
                    AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Analysis_CID)) = AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Analysis_CID)) + 1;
                    AST_COORD{AT_COORD(DB_NODES{i}.Analysis_CID)}.Node_list(AST_Coord_Nodes_counter(AT_COORD(DB_NODES{i}.Analysis_CID))) = DB_NODES{i}.ID;
                end
            
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end
        
    end
    
end

% --- Работа с базой Property sets ---

if (~isempty(DB_PSETS))
    
    % Заполнение списков property sets
    
    for i=1:size(DB_PSETS,1)
        
        if (DB_PSETS{i}.ID ~= -1)
            
            if (~isempty(AST_COORD))
                switch DB_PSETS{i}.type
                    case 'PSOLID'
                        if (DB_PSETS{i}.Ori_CID > 0)
                            AST_Coord_PSets_counter(AT_COORD(DB_PSETS{i}.Ori_CID)) = AST_Coord_PSets_counter(AT_COORD(DB_PSETS{i}.Ori_CID)) + 1;
                            AST_COORD{AT_COORD(DB_PSETS{i}.Ori_CID)}.PSet_list(AST_Coord_PSets_counter(AT_COORD(DB_PSETS{i}.Ori_CID))) = DB_PSETS{i}.ID;
                        end
                    case {'PCOMP', 'PCOMPG', 'PSHELL'}
                        if (~DB_Field_Isempty(DB_PSETS{i}.Ori_Field_ID))
                            SHELL_CID_counter = 0;
                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(1) == 0)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2) > 0)
                                    SHELL_CID_counter = SHELL_CID_counter + 1;
                                end
                            end
                            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data, 1)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data{j} ~= -1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                                            SHELL_CID_counter = SHELL_CID_counter + 1;
                                        end
                                    end
                                end
                            end
                            if (SHELL_CID_counter > 0)
                                SHELL_CID_Array = zeros(SHELL_CID_counter,1);
                                SHELL_CID_counter = 0;
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(1) == 0)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2) > 0)
                                        SHELL_CID_counter = SHELL_CID_counter + 1;
                                        SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Default(2);
                                    end
                                end
                                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data, 1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.ID_data{j} ~= -1)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                                                SHELL_CID_counter = SHELL_CID_counter + 1;
                                                SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_Field_ID)}.Value_data{j}(2);
                                            end
                                        end
                                    end
                                end
                                SHELL_CID_Array = unique(SHELL_CID_Array);
                                for j=1:size(SHELL_CID_Array,1)
                                    AST_Coord_PSets_counter(AT_COORD(SHELL_CID_Array(j))) = AST_Coord_PSets_counter(AT_COORD(SHELL_CID_Array(j))) + 1;
                                    AST_COORD{AT_COORD(SHELL_CID_Array(j))}.PSet_list(AST_Coord_PSets_counter(AT_COORD(SHELL_CID_Array(j)))) = DB_PSETS{i}.ID;
                                end
                            end
                        end
                    case 'PBUSH'
                        if (~DB_Field_Isempty(DB_PSETS{i}.Ori_CID_Field_ID))
                            PBUSH_CID_counter = 0;
                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default > 0)
                                PBUSH_CID_counter = PBUSH_CID_counter + 1;
                            end
                            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data, 1)
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                                        PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                    end
                                end
                            end
                            if (PBUSH_CID_counter > 0)
                                PBUSH_CID_Array = zeros(PBUSH_CID_counter,1);
                                PBUSH_CID_counter = 0;
                                if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default > 0)
                                    PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                    PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Default;
                                end
                                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data, 1)
                                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                                            PBUSH_CID_counter = PBUSH_CID_counter + 1;
                                            PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{i}.Ori_CID_Field_ID)}.Value_data{j};
                                        end
                                    end
                                end
                                PBUSH_CID_Array = unique(PBUSH_CID_Array);
                                for j=1:size(PBUSH_CID_Array,1)
                                    AST_Coord_PSets_counter(AT_COORD(PBUSH_CID_Array(j))) = AST_Coord_PSets_counter(AT_COORD(PBUSH_CID_Array(j))) + 1;
                                    AST_COORD{AT_COORD(PBUSH_CID_Array(j))}.PSet_list(AST_Coord_PSets_counter(AT_COORD(PBUSH_CID_Array(j)))) = DB_PSETS{i}.ID;
                                end
                            end
                        end
                    case {'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
                        % Ничего не делаем
                    otherwise
                        fprintf (1, '\nОбнаружен неизвестный тип property set с номером %i [%s] !\n', DB_PSETS{i}.ID, DB_PSETS{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;
                end
            end
            
            if (~isempty(AST_MATERIALS))
                switch DB_PSETS{i}.type
                    case {'PCOMP', 'PCOMPG'}
                        Mat_array = unique(DB_PSETS{i}.Laminate(:,1));
                        for j=1:size(Mat_array,1)
                            AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) = AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) + 1;
                            AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list(AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j)))) = DB_PSETS{i}.ID;
                        end
                    case 'PSHELL'
                        Mat_array = zeros(3,1);
                        Mat_array(1) = DB_PSETS{i}.Mat_ID_membrane;
                        Mat_array(2) = DB_PSETS{i}.Mat_ID_bending;
                        Mat_array(3) = DB_PSETS{i}.Mat_ID_transverse_shear;
                        Mat_array = unique(Mat_array);
                        for j=1:size(Mat_array,1)
                            AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) = AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j))) + 1;
                            AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list(AST_Mat_PSets_counter(AT_MATERIALS(Mat_array(j)))) = DB_PSETS{i}.ID;
                        end
                    case 'PBUSH'
                        % Ничего не делаем
                    case {'PSOLID', 'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
                        AST_Mat_PSets_counter(AT_MATERIALS(DB_PSETS{i}.Mat_ID)) = AST_Mat_PSets_counter(AT_MATERIALS(DB_PSETS{i}.Mat_ID)) + 1;
                        AST_MATERIALS{AT_MATERIALS(DB_PSETS{i}.Mat_ID)}.PSet_list(AST_Mat_PSets_counter(AT_MATERIALS(DB_PSETS{i}.Mat_ID))) = DB_PSETS{i}.ID;
                    otherwise
                        fprintf (1, '\nОбнаружен неизвестный тип property set с номером %i [%s] !\n', DB_PSETS{i}.ID, DB_PSETS{i}.type);
                        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
                        ErrCode = -1;
                        return;
                end
            end
            
        end
        
        % Для вывода прогресса
        PB_items_counter = PB_items_counter + 1;
        PB_current_progress = PB_items_counter / PB_N_items_total;
        if (PB_current_progress - PB_last_progress >= PB_progress_per_segment)
            while ((PB_N_bars_written+1)/PB_segments <= PB_current_progress)
                fprintf (1, '%s', PB_sign);
                pause (Progress_Bar_Delay);
                PB_N_bars_written = PB_N_bars_written + 1;
            end
            PB_last_progress = PB_current_progress;
        end
        
    end
    
end

% Для вывода прогресса
while(PB_N_bars_written < PB_segments)
    fprintf (1, '%s', PB_sign);
    pause (Progress_Bar_Delay);
    PB_N_bars_written = PB_N_bars_written + 1;
end

fprintf (1, ' OK!\n');
